#include "asciifreqanalysis.h"
#include "ui_asciifreqanalysis.h"

#include <QFile>
#include <QtDebug>
#include <QSettings>
#include <QTextStream>
#include <QFileDialog>
#include <QSqlDatabase>
#include <QSqlQuery>
#include <QSqlRecord>
#include <QSqlError>
#include <QThread>

#include "globalDefines.h"
#include "task/frequencyanalysis.h"
#include "loadingform.h"

AsciiFreqAnalysis::AsciiFreqAnalysis(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::AsciiFreqAnalysis)
{
//    absFreqs = NULL;
    ui->setupUi(this);
}

AsciiFreqAnalysis::~AsciiFreqAnalysis()
{
    delete ui;
}

void AsciiFreqAnalysis::on_load_clicked()
{
    QString fileName = QFileDialog::getOpenFileName(this, tr("Open File"));
    if (fileName.isNull()) return;
    QFile inputFile(fileName);
    inputFile.open(QIODevice::ReadOnly);
    ui->input->setBinaryData(inputFile.readAll());
}

void AsciiFreqAnalysis::on_analyze_clicked()
{
    QString fileName = QFileDialog::getSaveFileName(this, tr("Open File"));
    if (fileName.isNull()) return;
    QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
    db.setDatabaseName(fileName);

    ui->load->setEnabled(false);
    ui->analyze->setEnabled(false);
    ui->maxLenght->setEnabled(false);
    ui->input->setReadOnly(true);
    LoadingForm * busyLabel = new LoadingForm("Analyzing file...", this);
    busyLabel->move((rect().bottomRight() - busyLabel->rect().bottomRight())/2);
    busyLabel->show();

    FrequencyAnalysis * worker = new FrequencyAnalysis(ui->maxLenght->currentIndex() + 1, ui->input->binaryData(), frequencies, this);
    connect(worker, SIGNAL(done(QString)), this, SLOT(onAnalyzeDone(QString)));
    connect(worker, SIGNAL(finished()), busyLabel, SLOT(deleteLater()));
    worker->start();

}

void AsciiFreqAnalysis::onAnalyzeDone(QString formattedOutput)
{
    ui->load->setEnabled(true);
    ui->analyze->setEnabled(true);
    ui->input->setReadOnly(false);
    ui->output->setPlainText(formattedOutput);
}

void AsciiFreqAnalysis::on_cEscape_clicked()
{
    ui->input->setEscapeMode(BinaryTextEdit::CEscape);
}

void AsciiFreqAnalysis::on_URLEscape_clicked()
{
    ui->input->setEscapeMode(BinaryTextEdit::URLEscape);
}

void AsciiFreqAnalysis::on_hex_clicked()
{
    ui->input->setEscapeMode(BinaryTextEdit::Hex);
}

void AsciiFreqAnalysis::on_base64_clicked()
{
    ui->input->setEscapeMode(BinaryTextEdit::Base64);
}

void AsciiFreqAnalysis::on_binaryMode_clicked(bool checked)
{
    if (checked)
    {
        if (ui->cEscape->isChecked())
            on_cEscape_clicked();
        else if (ui->URLEscape->isChecked())
            on_URLEscape_clicked();
        else if (ui->hex->isChecked())
            on_hex_clicked();
        else // ui->base64->isChecked()
            on_base64_clicked();
    }
    else
    ui->input->setEscapeMode(BinaryTextEdit::None);
}

void AsciiFreqAnalysis::on_loadFreqs_clicked()
{
    QString fileName = QFileDialog::getOpenFileName(this, tr("Open File"));
    if (fileName.isNull()) return;
    QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
    db.setDatabaseName(fileName);

    if (!db.open())
    {
        qDebug() << "impossibile aprire il file";
        return;
    }

    QSqlQuery q = db.exec("SELECT * FROM frequencies");
    if (!q.isActive())
    {
        qDebug() << "il file delle frequenze non è valido (la tabella \"frequencies\" non esiste)";
        return;
    }
//    QHash<QByteArray, int> frequencies;
    int dataLenght = 0;
    foreach (QByteArray letter, frequencies.keys())
        if (letter.length() == 1) dataLenght += frequencies[letter];
    int keyField = q.record().indexOf("key");
    int freqField = q.record().indexOf("absFreq");
    if (keyField == -1 || freqField == -1)
    {
        qDebug() << "il file delle frequenze non è valido (campi non presenti nella tabella \"frequencies\")";
        return;
    }

    while (q.next())
    {
        dataLenght += frequencies[q.value(keyField).toByteArray()] = q.value(freqField).toInt();
    }

    //format output
    QString output;
    QTextStream outputStream(&output);
    QList<QByteArray> keys = frequencies.keys();
    qSort(keys.begin(), keys.end(), lessThanByLenght);

    int l = 1;
    foreach (QByteArray key, keys)
    {
        if (l < key.length())
        {
            outputStream << "\n";
            l = key.length();
        }
        outputStream << "\"" << key << "\" => " << QString::number(qreal(frequencies[key])/dataLenght) << "\n";
    }
    outputStream << "\nTotale: " << QString::number(dataLenght);
    outputStream.flush();
    ui->output->setPlainText(output);
    ui->maxLenght->setCurrentIndex(l-1);
    ui->maxLenght->setEnabled(false);
}

void AsciiFreqAnalysis::on_clear_clicked()
{
    frequencies.clear();
    ui->maxLenght->setEnabled(true);
}
